import React, { Dispatch, useEffect, useState } from 'react';
import {
  Button,
  Checkbox,
  Divider,
  Empty,
  Message,
  Skeleton,
} from '@arco-design/web-react';
import styles from '../../style/index.module.less';
import {
  PermissionByRoleId,
  PermissionSetByRoleId,
} from '@/api/modules/authentication';
import { Menu, Role } from '@/api/interface/authentication';

const CheckboxGroup = Checkbox.Group;
const useCheckbox = Checkbox.useCheckbox;

const getFlatMenuList = (menuList: Menu[]): Menu[] => {
  const newMenuList: Menu[] = JSON.parse(JSON.stringify(menuList));
  return newMenuList.flatMap((item) => [
    item,
    ...(item.children ? getFlatMenuList(item.children) : []),
  ]);
};

interface SelectId {
  [key: string]: number[];
}

interface ItemProp {
  item: Menu;
  defaultIds: number[];
  selectIds: SelectId;
  setSelectIds: Dispatch<React.SetStateAction<SelectId>>;
}

const PermissionItem = ({
  item,
  defaultIds,
  selectIds,
  setSelectIds,
}: ItemProp) => {
  const {
    selected,
    selectAll,
    setSelected,
    unSelectAll,
    isAllSelected,
    isPartialSelected,
  } = useCheckbox(
    item.children.map((v) => v.id),
    defaultIds
  );

  const [initialRender, setInitialRender] = useState(true);

  useEffect(() => {
    if (initialRender) {
      setInitialRender(false);
    } else {
      setSelectIds({ ...selectIds, [item.name]: selected });
    }
  }, [selected]);

  return (
    <div className={styles['permission-item']}>
      <Checkbox
        className={styles['permission-checkbox']}
        onChange={(checked) => {
          if (checked) selectAll();
          else unSelectAll();
        }}
        checked={isAllSelected()}
        indeterminate={isPartialSelected()}
      >
        <span className={styles['permission-title']}>{item.name}</span>
      </Checkbox>

      <CheckboxGroup
        value={selected}
        options={item.children?.map((v) => {
          return { label: v.name, value: v.id };
        })}
        onChange={setSelected}
        className={styles['permission-checkbox-group']}
      />
    </div>
  );
};

const RolePermissions = ({ t, role }: { t: unknown; role: Role }) => {
  const [loading, setLoading] = useState(false);
  useEffect(() => {
    role.id && getPermissionsList();
  }, [role.id]);

  const [defaultIds, setDefaultIds] = useState<number[]>();
  const [selectIds, setSelectIds] = useState<SelectId>({});
  const [permission, setPermissionList] = useState<Menu[]>([]);

  const getPermissionsList = async () => {
    try {
      setLoading(true);
      const { data } = await PermissionByRoleId({ roleId: role.id });
      const filteredMenus = data.menus.filter((item) => item.children?.length);
      setPermissionList(filteredMenus);

      const dIds = getFlatMenuList(filteredMenus)
        .filter((item) => item.checked)
        .map((item) => item.id);
      setDefaultIds(dIds);

      const SIds = {};
      filteredMenus.forEach((item) => {
        const checkedChildren = item.children?.filter((child) => child.checked);
        if (checkedChildren && checkedChildren.length > 0) {
          SIds[item.name] = checkedChildren.map((child) => child.id);
        }
      });
      setSelectIds(SIds);
    } finally {
      setLoading(false);
    }
  };

  const [saveLoading, setSaveLoading] = useState(false);
  const savePermission = async () => {
    const filteredData = Object.fromEntries(
      Object.entries(selectIds).filter(([key, value]) => value.length > 0)
    );
    const parentIds = permission.reduce((ids, item) => {
      filteredData.hasOwnProperty(item.name) && ids.push(item.id);
      return ids;
    }, []);
    const allValues = Object.values(selectIds).flat(Infinity);
    // console.log(selectIds);
    // console.log([...parentIds, ...allValues]);
    try {
      setSaveLoading(true);
      await PermissionSetByRoleId({
        menuIds: [...parentIds, ...allValues],
        // operatorId: 1,
        roleId: role.id,
      });
      Message.success(t['auth.save.success']);
    } finally {
      setSaveLoading(false);
    }
  };

  return (
    <div className={styles['role-permission']}>
      <Skeleton text={{ rows: 14 }} loading={loading}>
        {permission.length ? (
          <>
            {permission.map((item) => {
              return (
                <div key={item.id}>
                  <PermissionItem
                    item={item}
                    defaultIds={defaultIds}
                    selectIds={selectIds}
                    setSelectIds={setSelectIds}
                  />
                  <Divider />
                </div>
              );
            })}
            <Button
              type="primary"
              className={styles['permission-button']}
              onClick={() => savePermission()}
              loading={saveLoading}
            >
              {t['auth.operations.save']}
            </Button>
          </>
        ) : (
          <Empty
            className={styles['role-empty']}
            style={{ margin: '50px 0' }}
          />
        )}
      </Skeleton>
    </div>
  );
};

export default RolePermissions;
